在前幾天,我們已經完成了數獨盤面的初始化、玩家輸入檢查、勝利判定與結束畫面。
今天的重點是進一步提升遊戲性:
通常,Sudoku 的難度取決於「保留的初始數字數量」:
type Difficulty int
const (
	Easy   Difficulty = 36
	Medium Difficulty = 32
	Hard   Difficulty = 28
)
// handleToggleLevelDifficultButton
func (gameLayout *GameLayout) handleToggleLevelDifficultButton() {
	if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
		xPos, yPos := ebiten.CursorPosition()
		if (xPos >= 4*cellSize && xPos <= 5*cellSize) &&
			(yPos >= cellSize && yPos <= 2*cellSize) {
			gameLayout.difficultyLevel = (gameLayout.difficultyLevel + 1) % len(difficultyOptions)
			gameLayout.ResetGameWithLevel()
		}
	}
	gameLayout.isPlayerWin = gameLayout.checkIfPlayerWin()
}
var difficultyOptions = [3]game.Difficulty{
	game.Easy,
	game.Medium,
	game.Hard,
}
var difficultyIcons = map[game.Difficulty]string{
	game.Easy:   "🐣", // 小雞
	game.Medium: "🦊", // 狐狸
	game.Hard:   "🦁", // 獅子
}
func getLevelIconColor(difficulty game.Difficulty) color.Color {
	switch difficulty {
	case game.Medium: // dark Red
		return color.RGBA{0xdc, 0x14, 0x3c, 0xff}
	case game.Hard, game.Easy: // Gold
		return color.RGBA{0xFF, 0xD7, 0x00, 0xFF}
	default: // 其他都是預設 白色
		return color.RGBA{0xFF, 0xFF, 0xFF, 0xFF}
	}
}
func (gameLayout *GameLayout) drawLevelButtonWithIcon(screen *ebiten.Image) {
	vector.DrawFilledCircle(screen, float32(ScreenWidth/2), cellSize+cellSize/2, 25,
		getIconColor(DarkButton),
		true,
	)
	gameDifficulty := difficultyOptions[gameLayout.difficultyLevel]
	levelIcon := difficultyIcons[gameDifficulty]
	emojiValue := levelIcon
	emojiXPos := ScreenWidth / 2
	emojiYPos := cellSize + cellSize/2
	emojiOpts := &text.DrawOptions{}
	emojiOpts.ColorScale.ScaleWithColor(getLevelIconColor(gameDifficulty))
	emojiOpts.PrimaryAlign = text.AlignCenter
	emojiOpts.SecondaryAlign = text.AlignCenter
	emojiOpts.GeoM.Translate(float64(emojiXPos), float64(emojiYPos))
	text.Draw(screen, emojiValue, &text.GoTextFace{
		Source: emojiFaceSource,
		Size:   30,
	}, emojiOpts)
}
我們需要一個簡單的「計時器」來追蹤遊戲時間。
思路如下:
func (game *Game) GetElaspedTime() int {
	return int(time.Since(game.StartTime).Seconds())
}
func (gameLayout *GameLayout) drawTimeLayout(screen *ebiten.Image) {
	elapsedSeconds := gameLayout.elapsedSeconds
	secondPart := elapsedSeconds % 60
	minutePart := (elapsedSeconds / 60) % 60
	textValue := fmt.Sprintf("%02d:%02d", minutePart, secondPart)
	textXPos := ScreenWidth - cellSize/4 + len(textValue)
	textYPos := cellSize / 2
	textOpts := &text.DrawOptions{}
	textOpts.ColorScale.ScaleWithColor(color.Black)
	textOpts.PrimaryAlign = text.AlignEnd
	textOpts.SecondaryAlign = text.AlignCenter
	textOpts.GeoM.Translate(float64(textXPos), float64(textYPos))
	text.Draw(screen, textValue, &text.GoTextFace{
		Source: mplusFaceSource,
		Size:   30,
	}, textOpts)
	emojiValue := "⏰"
	emojiXPos := ScreenWidth - 3*cellSize + len(emojiValue)
	emojiYPos := cellSize / 2
	emojiOpts := &text.DrawOptions{}
	emojiOpts.ColorScale.ScaleWithColor(getIconColor(IsClock))
	emojiOpts.PrimaryAlign = text.AlignStart
	emojiOpts.SecondaryAlign = text.AlignCenter
	emojiOpts.GeoM.Translate(float64(emojiXPos), float64(emojiYPos))
	text.Draw(screen, emojiValue, &text.GoTextFace{
		Source: emojiFaceSource,
		Size:   30,
	}, emojiOpts)
}



https://github.com/leetcode-golang-classroom/sudoku-game/actions/runs/17606836599/job/50019346536
這樣玩家就能挑戰更高難度,並追求更快的完成速度。
明天的內容將進一步改善 遊戲的互動體驗:
我們將加入「數字快捷選擇面板」與「高亮提示」,讓玩家能更直覺輸入與觀察數字,提升遊戲流暢度。